
#include <iostream>
#include <list>
#include <string>
#include <vector>

#include <cstring>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/stat.h>
#include <netinet/tcp.h>

#include <iomanip>
#include <cstdint>
#include <cctype>
#include <fcntl.h>

#include "common.hpp"
#include "log.h"
#include "config.h"

using namespace std;

uint64_t htonll(uint64_t val)
{
	return (((uint64_t) htonl(val)) << 32) + htonl(val >> 32);
}

uint64_t ntohll(uint64_t val)
{
	return (((uint64_t) ntohl(val)) << 32) + ntohl(val >> 32);
}

/* 检测并创建目录 */
void create_directory(const string& directory_path) {
	struct stat dir_stat;
	if (stat(directory_path.c_str(), &dir_stat) == 0) { // 已经存在
		if (S_ISDIR(dir_stat.st_mode)) {//路径为目录
			return;
		} else {
			remove(directory_path.c_str()); //路径不是目录，需要删除后重新创建
		}
	}

	string dir_name = directory_path;
	if (dir_name.back() != '/') {
		dir_name += '/';
	}
	size_t len = dir_name.length();
	for (size_t i = 1; i < len; ++i) {
		if (dir_name[i] == '/') {
			char temp = dir_name[i];
			dir_name[i] = '\0';
			if (access(dir_name.c_str(), 0) != 0) {
				if (mkdir(dir_name.c_str(), 0755) == -1) {
					return;
				}
			}
			dir_name[i] = temp;
		}
	}
}

void create_directory(const char* directory_path)
{
	create_directory(string(directory_path));
}

/* 删除目标目录 */
void remove_directory(const string& directory_path) {
	if (access(directory_path.c_str(), F_OK) != 0) { // 文件夹不存在
		return;
	}
	struct stat dir_stat;
	if (stat(directory_path.c_str(), &dir_stat) < 0) {
		cerr << "get " << directory_path << " stat error!" << endl;
		return;
	}
	if (S_ISREG(dir_stat.st_mode)) { // 常规文件直接remove
		remove(directory_path.c_str());
	} else if (S_ISDIR(dir_stat.st_mode)) { // 目录文件需要递归删除
		cout << "path_name is dir, openit" << endl;
		DIR* dirp = opendir(directory_path.c_str());
		if (!dirp) {
			return;
		}
		struct dirent* dir;
		while ((dir = readdir(dirp)) != nullptr) {
			if (!strncasecmp(dir->d_name, ".", 1) ||
				!strncasecmp(dir->d_name, "..", 2)) {
				continue;
			}
			string sub_path = directory_path + "/" + dir->d_name;
			remove_directory(sub_path); // 递归调用程序
		}
		closedir(dirp);
		rmdir(directory_path.c_str());
	}
}
void remove_directory(const char* directory_path)
{
	remove_directory(string(directory_path));
}
/* 设置 TCP 关闭 Nagle算法 */
bool net_optimize_disable_Nagle(int fd)
{
        int flag = 1;
        if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &flag, sizeof(flag)) < 0) {
                std::cerr << "Failed to set TCP_NODELAY option" << std::endl;
                return false;
        }
        return true;
}
/* 设置TCP 快速ACK 需要每次recv 后设置 */
bool net_optimize_enableQuickAck(int fd)
{
        int flag = 1;
        if (setsockopt(fd, IPPROTO_TCP, TCP_QUICKACK, &flag, sizeof(flag)) == -1) {
                std::cerr << "Failed to enable TCP quickack: " << std::strerror(errno) << std::endl;
                return false;
        }
        return true;

}
/* 设置 TCP recv 缓冲区大小 */
bool net_optimize_setReceiveBuffer(int fd, size_t _size)
{
        size_t set_size = _size;
        if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &set_size, sizeof(set_size)) == -1) {
                std::cerr << "Failed to set receive buffer size: " << std::strerror(errno) << std::endl;
                return false;
        }
        // 验证实际设置的大小
        size_t actualSize = 0;
        socklen_t len = sizeof(actualSize);
        if (getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &actualSize, &len) == -1) {
                std::cerr << "Failed to get actual receive buffer size: " << std::strerror(errno) << std::endl;
                return false;
        }
        return true;
}

// 封装创建 套接字并绑定的函数
int create_bind_net_socket(int __type, const char* ip, int port)
{
        if (__type != SOCK_DGRAM && __type != SOCK_STREAM) {
                sys_err ("Invalid socket type: %d\n", __type);
                return -1;
        }
        if (port <= 0 || port > 65535) {
                sys_err("Invalid port number: %d\n", port);
                return -1;
        }
	// 创建 UDP 套接字
	int sockfd = socket(AF_INET, __type, 0);
	if (sockfd == -1) {
		sys_err("creat %s socket err!%d(%s)\n", (__type == SOCK_STREAM)?"TCP":"UDP", errno, strerror(errno));
		Lzlog_error("creat %s socket err!%d(%s)", (__type == SOCK_STREAM)?"TCP":"UDP", errno, strerror(errno));
		return -1;
	}
	sys_debug("creat %s socket OK!fd:%d\n", (__type == SOCK_STREAM)?"TCP":"UDP", sockfd);

        int opt = 1;
        if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1) {
                perror("setsockopt failed");
                close(sockfd);
                return -1;
        }

	// 配置服务器地址
	struct sockaddr_in local_addr;
	memset(&local_addr, 0, sizeof(local_addr));
	local_addr.sin_family = AF_INET;
	local_addr.sin_port = htons(port);
        if (strcmp(ip, "0.0.0.0") == 0) {
                local_addr.sin_addr.s_addr = INADDR_ANY;
        } else {
                if (inet_pton(AF_INET, ip, &local_addr.sin_addr) <= 0) {
                        sys_err("Invalid address or address not supported!%d(%s)\n", errno, strerror(errno));
                        Lzlog_error("Invalid address or address not supported!%d(%s)", errno, strerror(errno));
                        close(sockfd);
                        return -1;
                }
        }

	// 绑定套接字到指定的 IP 地址和端口号
	if (bind(sockfd, (struct sockaddr*)&local_addr, sizeof(local_addr)) == -1) {
		sys_err("Bind failed!%d(%s)\n", errno, strerror(errno));
		Lzlog_error("Bind failed!%d(%s)", errno, strerror(errno));
		close(sockfd);
		return -1;
	}
	sys_info("Create %s socket and Bind IP:%s, port:%d, Success!,fd:%d\n", (__type == SOCK_STREAM)?"TCP":"UDP", ip, port, sockfd);
	Lzlog_debug("Create %s socket and Bind IP:%s, port:%d, Success!,fd:%d\n", (__type == SOCK_STREAM)?"TCP":"UDP", ip, port, sockfd);
        if (__type == SOCK_STREAM) {
                if (listen(sockfd, 20) == -1) {
                        sys_err("listen failed!%d(%s)\n", errno, strerror(errno));
                        Lzlog_error("listen failed!%d(%s)", errno, strerror(errno));
                        close(sockfd);
                        return -1;
                }
        }
	return sockfd;
}

int setnonblocking(int fd)
{
	int flags;
	if (-1 == (flags = fcntl(fd, F_GETFL, 0))) {
		flags = 0;
	}
	return fcntl(fd, F_SETFL, flags | O_NONBLOCK);
}

uint64_t BytesStringToBytes(const char *size_str)
{
	string str = string(size_str);
	string num_str;
	string unit_str;

	string upper_str = str;

	for (char& c : upper_str) {
		c = toupper(c);
	}

	for (char c : upper_str) {
		if (isdigit(c)) {
			num_str += c;
		} else if (!isspace(c)) {
			unit_str += c;
		}
	}

	uint64_t num = stoll(num_str);

	if (unit_str == "B") {
		return num;
	} else if (unit_str == "KB") {
		return num * KB;
	} else if (unit_str == "MB") {
		return num * MB;
	} else if (unit_str == "GB") {
		return num * GB;
	} else {
		throw invalid_argument("Unsupport: " + unit_str);
	}
}

void dump_hex(const uint8_t *buf, uint32_t size, uint32_t number)
{
	for (uint32_t i = 0; i < size; i += number) {
		cout << hex << setw(8) << setfill('0') << i << ": ";

		for (uint32_t j = 0; j < number; j++) {
			if (j % 8 == 0) {
				cout << " ";
			}
			if (i + j < size)
				cout << hex << setw(2) << setfill('0') << static_cast<int>(buf[i + j]) << " ";
			else
				cout << "   ";
		}
		cout << " ";

		for (uint32_t j = 0; j < number; j++) {
			if (i + j < size) {
				cout << (isprint(buf[i + j]) ? static_cast<char>(buf[i + j]) : '.');
			}
		}
		cout << endl;
	}
}
int is_tcpdump_data(const char *data, size_t len)
{
        // 检查是否包含tcpdump特征字符串
        if (len >= 20) {
        // 检查是否以"reading from file"开头
        if (strncmp(data, "reading from file", 17) == 0) {
                return 1;
        }

        // 检查是否以时间戳格式开头 (HH:MM:SS)
        if (isdigit(data[0]) && isdigit(data[1]) &&
                data[2] == ':' && isdigit(data[3]) &&
                isdigit(data[4]) && data[5] == ':') {
                return 1;
        }

        // 检查是否包含IP数据包指示符
        if (strstr(data, " IP ") != NULL) {
                return 1;
        }
        }

        return 0;
}